#include "serial.h"

int serial_set_opt(int fd,int nSpeed,int nBits,char nEvent,int nStop){
	struct termios newtio,oldtio;

	if(tcgetattr(fd,&oldtio) != 0){
		perror("Setup Serial 1");
		printf("tcgetattr(fd,&oldtio) -> %d\n",tcgetattr(fd,&oldtio));
		return -1;
	}

	bzero(&newtio,sizeof(newtio));

	/* 设置字符大小 */
	newtio.c_cflag |= CLOCAL | CREAD;
	newtio.c_cflag &= ~CSIZE;

	/* 设置数据位 */
	switch(nBits){
		case 7: newtio.c_cflag |= CS7;
			break;
		case 8: newtio.c_cflag |= CS8;
			break;		
	}

	/* 设置奇偶校验 */
	switch(nEvent){
		case 'o':
		case 'O'://奇数
			newtio.c_cflag |= PARENB;
			newtio.c_cflag |= PARODD;
			newtio.c_iflag |= (INPCK | ISTRIP);
			break;
		case 'e':
		case 'E'://偶数
			newtio.c_iflag |= (INPCK | ISTRIP);
			newtio.c_cflag |= PARENB;
			newtio.c_cflag &= ~PARODD;			
			break;
		case 'n':
     	case 'N':  //无奇偶校验位 
      		newtio.c_cflag &= ~PARENB; 
      		break;
     	default:
      		break;
	}

	/* 设置波特率 */
	switch( nSpeed ){ 
		case 2400: 
			cfsetispeed(&newtio, B2400); 
			cfsetospeed(&newtio, B2400); 
			break; 
		case 4800: 
			cfsetispeed(&newtio, B4800); 
			cfsetospeed(&newtio, B4800); 
			break; 
		case 9600: 
			cfsetispeed(&newtio, B9600); 
			cfsetospeed(&newtio, B9600); 
			break; 
		case 115200: 
			cfsetispeed(&newtio, B115200); 
			cfsetospeed(&newtio, B115200); 
			break; 
		case 460800: 
			cfsetispeed(&newtio, B460800); 
			cfsetospeed(&newtio, B460800); 
			break; 
		default: 
			cfsetispeed(&newtio, B9600); 
			cfsetospeed(&newtio, B9600); 
			break; 
     } 
	/*设置停止位*/ 
	if( nStop == 1 ) 
      	newtio.c_cflag &=  ~CSTOPB; 
	else if ( nStop == 2 ) 
      	newtio.c_cflag |=  CSTOPB; 
	/*设置等待时间和最小接收字符*/ 
	newtio.c_cc[VTIME]  = 0; 
	newtio.c_cc[VMIN] = 0; 
	/*处理未接收字符*/ 
	tcflush(fd,TCIFLUSH); 
	/*激活新配置*/ 
	if((tcsetattr(fd,TCSANOW,&newtio))!=0) 
	{ 
		perror("com set error"); 
		return -1; 
	} 

	printf("set done!\n"); 
	return 0; 

}

/* 模拟通信协议
 * 帧头 	帧类型 	帧长度（数据区的帧长度）	校验帧
 * 0XAA 	0XCB	0X05				和
 * AA CB 05 FE EE 5A E2 C3 XX(校验和)
 */


static uint8_t cal_write_data_checksum(H6_Write_Data *buf,int num)
{
	uint8_t checksum = 0;
	int i;
	checksum += buf->FrameHeader;
	checksum += buf->FrameType;
	checksum += buf->FrameLength;
	for(i=0;i<buf->FrameLength;i++){
		checksum += buf->FrameDataAdress[i];
	}
//	checksum = 0XFF - checksum % 256;
	checksum = checksum % 256;
	return checksum;
}


void *serial_read_pthread(void *arg)//串口读数据线程
{
	s_read_arg *s_arg = (s_read_arg *)arg;	
	int length = 0;
	uint8_t data = 0;
	Read_Enum readenum = FrameHead;
	static uint8_t check_sum = 0;
	while(1)
	{
		read(s_arg->fd,&data,1);
		switch(readenum)
		{
			case FrameHead:
			       if(data !=  UART3_FRAME_HEAD)	
			       {
				       readenum = FrameHead;
				       check_sum = 0;
			       }
			       else{//帧头接收成功
				       readenum = FrameType;
				       printf("head success! \n");
					   check_sum += data;
					   s_arg->read_data.FrameHeader = data;						
			       }
			break;

			case FrameType:
				if(data != UART3_FRAME_TYPE_DATA){
					readenum = FrameHead;
					check_sum = 0;
					printf("error 2 !\n");
				}
				else{//帧类型接收成功
					readenum = FrameLength;
					check_sum += data;
					s_arg->read_data.FrameType = data;
				}
			break;

			case FrameLength:
				if(data > UART3_FRAME_DATA_MAX_SIZE){
					readenum = FrameHead;
					check_sum = 0;
					printf("error 3 !\n");
				}
				else{//帧长度接收成功
					readenum = FrameData;
					check_sum += data;
					s_arg->read_data.FrameLength = data;
				}
			break;

			case FrameData:		//帧数据接收		
				check_sum += data;
				s_arg->read_data.FrameDataAdress[length++] = data;
				if(length == s_arg->read_data.FrameLength){
					readenum = FrameCheck;
					length = 0;
				}
			break;

			case FrameCheck:
				if(data != check_sum){
					readenum = FrameHead;
					check_sum = 0;//校验出错  重新接收
					printf("error 4 !\n");
				}
				else{//校验成功
					readenum = FrameHead;
					check_sum = 0;
					s_arg->read_data.FrameCheck = data;
					s_arg->read_data.IsSuccessRecieve = true;
					printf("read ok!\n");
				}
			break;

		}		
	}	
}


void *serial_write_pthread(void *arg)//串口写数据程序
{
	s_write_arg *s_arg = (s_write_arg *)arg;
	while(1)
	{
		if(s_arg->write_data.IsSuccessSend == false){		
			write(s_arg->fd,&(s_arg->write_data.FrameHeader),1);
			write(s_arg->fd,&(s_arg->write_data.FrameType),1);
			write(s_arg->fd,&(s_arg->write_data.FrameLength),1);
			write(s_arg->fd,(s_arg->write_data.FrameDataAdress),(s_arg->write_data.FrameLength));
			write(s_arg->fd,&(s_arg->write_data.FrameCheck),1);
			s_arg->write_data.IsSuccessSend = true;
		}
	}
}

static char *array_to_char(char *arr,int len)
{
	int i ;
	char * str = (char*)malloc(len);
	for(i = 0;i<len;i++)
	{
		str[i] = arr[i];
	}
	str[len] = '\0';
	return str;
}

static int string_cmp(char *a,char *b,int len)
{
	int i;
	if(len == 0)
	{
		return -1;
	}
	for(i = 0;i<len;i++)
	{
		if(a[i] != b[i])
		{
			return -1;

		}
	}
	return 0;
}

int main(void)
{
    char *uart3 = (char*)"/dev/ttyS0";
//    size_t read_len = 0;	//这里写size_t会一直返回-1 然后他还能通过>0 的判断疯狂打印
    uint8_t buf[32] = {0xEE,0xFF,0xCA,0xDA,0xDD};
    int i = 1;
    int ret = 0;
    pthread_t id1,id2;
    s_read_arg r_arg;
    s_write_arg w_arg;
	

//    memset(buf,0,sizeof(buf));
    r_arg.fd = open(uart3,O_RDWR|O_NONBLOCK);
    w_arg.fd = r_arg.fd;
    if(r_arg.fd < 0)
    {
        printf("open uart3 failed\n");
    }

    ret = pthread_create(&id1,NULL,(void *)serial_read_pthread,(void *)&r_arg);
    if(ret)
    {
        printf("create error\n");
        return -1;
    }
    ret = pthread_create(&id2,NULL,(void *)serial_write_pthread,(void *)&w_arg);
    if(ret)
    {
        printf("create error\n");
        return -1;
    }

	w_arg.write_data.IsSuccessSend = false;
	w_arg.write_data.FrameHeader = UART3_FRAME_HEAD;
	w_arg.write_data.FrameType = UART3_FRAME_TYPE_RESPOND;
	w_arg.write_data.FrameLength = UART3_FRAME_LENGTH;
	memcpy(w_arg.write_data.FrameDataAdress,buf,w_arg.write_data.FrameLength);
	w_arg.write_data.FrameCheck = cal_write_data_checksum(&(w_arg.write_data),(w_arg.write_data.FrameLength+4));

    while(1)
    {
	    i *= 2;
    }

    pthread_join(id1,NULL);
    pthread_join(id2,NULL);
    close(r_arg.fd);
}
